package it.uniroma2.jcloudstests;

import it.uniroma2.cloud.PROVIDER;
import it.uniroma2.cloud.ProviderFactory;
import it.uniroma2.cloud.util.ProviderHelper;
import it.uniroma2.cloud.util.ProviderHelperFactory;
import it.uniroma2.cloud.util.PropertiesMap.CloudProviderProperty;

import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

import org.jclouds.chef.ChefContext;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.RunScriptOnNodesException;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.Statements;

public class Command {

	private static final PROVIDER provider = PROVIDER.OPENSTACK; // may be
																	// PROVIDER.CLOUDSTACK
	public static final String WORKERNODE = "worker-node";
	public static final String MONITORING = "monitoring";
	public static final String LOADBALANCER = "loadbalancer";
	public static final String CONTROLLER = "controller";
	public static final String CLIENT = "client";

	private ComputeService computeService;
	private ProviderHelper helper;

	public Command(ComputeService computeService, ProviderHelper helper) {
		super();
		this.computeService = computeService;
		this.helper = helper;
	}

	public void printNodeGroup(String group) {
		System.out.println("===Node Group: " + group);
		Iterable<? extends NodeMetadata> nodes = helper
				.listRunningNodesInGroup(computeService, group);
		Iterator<? extends NodeMetadata> nodeIt = nodes.iterator();
		while (nodeIt.hasNext()) {
			NodeMetadata node = nodeIt.next();
			System.out.println(node);
		}
	}

	public Set<? extends NodeMetadata> createInstances(String group, int howMany)
			throws RunNodesException {
		Template t = helper.getTemplate(computeService);
		Set<? extends NodeMetadata> nodeSet = computeService
				.createNodesInGroup(group, howMany, t);

		Iterator<? extends NodeMetadata> itNode = nodeSet.iterator();
		while (itNode.hasNext()) {
			NodeMetadata node = (NodeMetadata) itNode.next();
			System.out.println(node);
		}
		return nodeSet;
	}

	public void installWorkerNodesOnDefaultImage(PROVIDER provider)
			throws RunScriptOnNodesException {
		helper.runScriptOnGroup(
				computeService,
				WORKERNODE,
				Statements.newStatementList(
						Statements.exec("apt-get -y update"),
						Statements.exec("apt-get -y install unzip"),
						Statements
								.exec("wget https://s3.amazonaws.com/TesiAndrianiFiorentino/hyperic-sigar-1.6.4.zip"),
						Statements.exec("unzip hyperic-sigar-1.6.4.zip"),
						Statements
								.exec("mv hyperic-sigar-1.6.4/sigar-bin/lib/* /lib"),
						Statements.exec("apt-get -y install tomcat7"),
						Statements.exec("apt-get -y install tomcat7-admin")));
	}

	public void installWorkerNodeApp(PROVIDER provider,
			Set<? extends NodeMetadata> nodeSet)
			throws RunScriptOnNodesException {
		Iterator<? extends NodeMetadata> itNode = nodeSet.iterator();
		while (itNode.hasNext()) {
			NodeMetadata node = (NodeMetadata) itNode.next();
			System.out.println(node.getId());

			helper.runScriptOnInstance(
					computeService,
					node.getId(),
					Statements.newStatementList(
							Statements
									.exec("wget https://s3.amazonaws.com/TesiAndrianiFiorentino/imagetranscoder.war"),
							Statements
									.exec("mv imagetranscoder.war /var/lib/tomcat7/webapps")));

		}
	}

	public void installWorkerNodeApp(PROVIDER provider)
			throws RunScriptOnNodesException {
		helper.runScriptOnGroup(
				computeService,
				WORKERNODE,
				Statements.newStatementList(
						Statements
								.exec("wget https://s3.amazonaws.com/TesiAndrianiFiorentino/imagetranscoder.war"),
						Statements
								.exec("mv imagetranscoder.war /var/lib/tomcat7/webapps")));

	}

	public void installClientNodes(PROVIDER provider)
			throws RunScriptOnNodesException {
		helper.runScriptOnGroup(
				computeService,
				CLIENT,
				Statements.newStatementList(
						Statements.exec("apt-get -y update"),
						Statements.exec("apt-get -y install openjdk-7-jdk"),
						Statements.exec("apt-get -y install unzip"))
//						Statements
//								.exec("wget https://s3.amazonaws.com/TesiAndrianiFiorentino/imgs.zip"),
//						Statements.exec("unzip imgs.zip"),
//						Statements.exec("mv imgs ~/"),
//						Statements
//								.exec("wget https://s3.amazonaws.com/TesiAndrianiFiorentino/client-0.0.1-SNAPSHOT-jar-with-dependencies.jar"),
//						Statements
//								.exec("mv client-0.0.1-SNAPSHOT-jar-with-dependencies.jar ~/"))

		);
	}

	

	public LoginCredentials getLoginCredentials() throws IOException {
		return helper.getLoginCredentials();
	}

	public Iterable<? extends NodeMetadata> listRunningNodesInGroup(String groupName) {
		return helper.listRunningNodesInGroup(computeService, groupName);
	}

	public void runScriptOnGroup(String groupName,
			Statement command) throws RunScriptOnNodesException {
		helper.runScriptOnGroup(computeService, groupName, command);	
	}

	public void runScriptOnInstance(String instanceName, Statement command)
			throws RunScriptOnNodesException {
		helper.runScriptOnInstance(computeService, instanceName, command);
	}

	public Template getTemplate() {
		return helper.getTemplate(computeService);
	}

//	public ChefContext buildChefContext() throws IOException {
//		return helper.buildChefContext();
//	}

	public void updateLoadBalancer(Collection<String> ips) {
		helper.updateLoadBalancer(computeService, ips);
	}

	public Collection<String> getPrivateIpsInGroup(String groupName) {
		return helper.getPrivateIpsInGroup(computeService, groupName);
	}
	
	public Collection<String> getReachableIpsInGroup(String groupName) {
		return helper.getReachableIpsInGroup(computeService, groupName);
	}
	
	public String getReachableIp(NodeMetadata node) {
		return helper.getReachableIp(computeService, node);
	}

	public void destroyNode(NodeMetadata node) {
		helper.destroyNode(computeService, node);
	}

	public NodeMetadata getNodeByReachableIp(String groupName, String ip) {
		return helper.getNodeByReachableIp(computeService, groupName, ip);
	}

	public String getLoadBalancerAddress() {
		return helper.getLoadBalancerAddress(computeService);
	}
	
	public String getMonitoringAddress(){
		return helper.getMonitoringAddress(computeService);
	}
	
	public int howManyRunningWorkerNodes(){
		return helper.howManyRunningWorkerNodes(computeService);
	}


	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) {
		ComputeService computeService = ProviderFactory
				.createComputeService(provider);
		ProviderHelper helper = ProviderHelperFactory
				.getProviderHelper(provider);
		try {
			Command cmd = new Command(computeService, helper);
//			System.out.println(cmd.getMonitoringAddress());
//			cmd.printNodeGroup(WORKERNODE);
			
			Set<? extends NodeMetadata> nodeSet = cmd.createInstances(
					WORKERNODE, 1);
			cmd.installWorkerNodesOnDefaultImage(provider);
//			System.out.println("howmany: " + cmd.howManyRunningWorkerNodes());
			
//			NodeMetadata node = cmd.helper.getNodeByPrivateIp(computeService, WORKERNODE, "192.168.3.53");
//			cmd.destroyNode(computeService, node);
//			Set<? extends NodeMetadata> nodeSet = cmd.createInstances(
//					WORKERNODE, 1);
//			cmd.installClientNodes(provider);
			// cmd.installWorkerNodes(provider);
//			cmd.installWorkerNodeApp(provider, nodeSet);

//			 Collection<String> ips = cmd.helper.getIpsInGroup(computeService,
//			 WORKERNODE);
//			 cmd.helper.updateLoadBalancer(computeService, ips);

//			cmd.createInstances(CONTROLLER, 1);
			// cmd.installClientNodes(provider);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			computeService.getContext().close();
		}
	}
	
}
